import wx
import wx.wizard
import contents
import images
import function
import mutation
import stop_condition
import select
import os
import project
from numpy import arange

class Singleton_Content(object):
    results=0
    project_name="a"
    
    alg_type="a"
    project_type="a"
    nruns=0
    
    function_c=0
    ag_c=0
    pop_c=0
    sel_c=0
    cross_c=0
    mut_c=0
    
    """Singleton that encapsulates the concreat DAO Object that DAOFactory returns."""
    def __new__(type):      
        if not '_the_instance' in type.__dict__:
            type._the_instance = object.__new__(type)
        return type._the_instance
    
class Crossover_Frame(wx.wizard.WizardPageSimple):
    def __init__(self, parent, title):
       
       wx.wizard.WizardPageSimple.__init__(self, parent)  
       self.recombination_panel = wx.Panel(self, -1)
       
       #self.Bind(wiz.EVT_WIZARD_CANCEL, self.OnWizCancel)
       self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.set_parameters)
       self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.post_processing)

    def set_parameters(self, event):
        
        a=Singleton_Content()
        
        self.project_type = a.project_type
        self.alg_type = a.alg_type
        
        #Fill Up the main panel of the Frame
        self.fill_up_recombination_data(self.recombination_panel)
        
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.sizer)
        self.sizer.Add(self.recombination_panel, 0, wx.EXPAND)
              
    def fill_up_recombination_data(self, panel):
        
        rec_prob_label=wx.StaticText(panel, -1, "Crossover Probability", pos=(10, 12))
        self.prob=wx.TextCtrl(panel, -1, "0.9", pos=(140, 10), size=(40, 20))
        self.prob.SetToolTip(wx.ToolTip("Probabilty to use crossover operator. (0-1)\n"))
                
        recombination_list=["One Point Crossover", "N Point Crossover", 
                       "Uniform Crossover"]
        
        rec_type_label=wx.StaticText(panel, -1, "Crossover Type", pos=(10, 42))
        self.rec_type = wx.ComboBox(panel, -1, "One Point Crossover", (100, 40), 
                           wx.DefaultSize,recombination_list, wx.CB_DROPDOWN)
        
        self.Bind(wx.EVT_COMBOBOX, self.OnRecSelect, self.rec_type)
        self.rec_type.SetToolTip(wx.ToolTip("Crossover Type:\n" +\
                                            "One point - Splits each gene of the parents in two, giving each half to one of the offspring\n"+\
                                            "N point - Splits each gene of the parents in n+1 parts, giving half of these to one of the offspring\n"+\
                                            "Uniform - Takes each of the parents' genes and generates one offspring with the average of each gene\n"))
        
        number_label=wx.StaticText(panel, -1, "Number Of Points", pos=(10, 72))
        self.number=wx.TextCtrl(panel, -1, "2", pos=(100, 70), size=(40, 20))
        self.number.SetToolTip(wx.ToolTip("Number of crossover points (1-N)"))
        self.number.Enable(False)

    def post_processing(self, event):
        
        if(not(self.validate())):
            dlg=wx.MessageDialog(self, "Values are not right!", "WRONG", wx.OK)
            dlg.ShowModal()
            dlg.Destroy()
            event.Veto()
        else:
            event.Allow()
            
        c = contents.content()
        
        c.prob=[None]
        c.npoints=[None]
        c.weight=[None]
	
        ##Crossover = [callable, range(prob), range(numPoints), range(weight)]
        
        if(self.project_type=="Quickshot"):
            c.prob = [float(self.prob.GetValue())]
            
            if self.rec_type.GetStringSelection()=="":
                c.type="One Point Crossover"
            else:
                c.type = self.rec_type.GetStringSelection()
            
            if(c.type == "N Point Crossover"):
                c.npoints = [int(self.number.GetValue())]
        else:    
            if self.rec_type.GetStringSelection()=="":
                c.type="One Point Crossover"
            else:
                c.type = self.rec_type.GetStringSelection()
            c.prob = arange(float(self.prob.GetValue()),\
                           float(self.topProb.GetValue()),\
                           float(self.stepProb.GetValue()))
            if(c.type == "N Point Crossover"):
                c.npoints = range(int(self.number.GetValue()),\
                                  int(self.top.GetValue()),\
                                  int(self.step.GetValue()))
            
        a=Singleton_Content
        a.cross_c=c
        
    def OnRecSelect(self, event):
        evtObj=event.GetEventObject()                
        chosen=evtObj.GetValue()
        
        if (chosen=="One Point Crossover"):
            self.number.Enable(False)
            if(self.project_type=="Longshot"):
                 self.OnRemoveRuns()
             
        
        if (chosen=="N Point Crossover"):
            self.number.Enable(True)
            if(self.project_type=="Longshot"):
                 self.OnAddRuns()
        
        if (chosen=="Uniform Crossover"):
            self.number.Enable(False)
            if(self.project_type=="Longshot"):
                 self.OnRemoveRuns()
            
    def OnAddRuns(self):

        self.top_label.Show(True)
        self.top.Show(True)
        self.step_label.Show(True)
        self.step.Show(True) 
        
    
    def validate(self):
        
        try:
            if float(self.prob.GetValue()) < 0 or float(self.prob.GetValue()) > 1 :
                return False
        except ValueError: return False

        return True
              
        
class Mutation_Frame(wx.wizard.WizardPageSimple):
    def __init__(self, parent, title):

    	wx.wizard.WizardPageSimple.__init__(self, parent)  
    	self.mutation_panel = wx.Panel(self, -1)
        
        #self.Bind(wiz.EVT_WIZARD_CANCEL, self.OnWizCancel)
        self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.set_parameters)
    	self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.post_processing)
        
        
    def set_parameters(self, event):
        a=Singleton_Content()
        
        self.project_type = a.project_type
        self.alg_type = a.alg_type
        
        #Fill Up the main panel of the Frame
        self.fill_up_mutation_data(self.mutation_panel, self.alg_type, self.project_type)
        
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.sizer)
        self.sizer.Add(self.mutation_panel , 0, wx.EXPAND)  
        
    def fill_up_mutation_data(self, panel, alg_type, project_type):
        
        #mutation_list=mutation.gimme_mutation_names()
        mutation_list=["One Bit Mutation", "Several Bits Mutation", "Bit Position Related Mutation"]
        
        mut_type_label=wx.StaticText(panel, -1, "Mutation Type", pos=(10, 12))
        self.mut_type = wx.ComboBox(panel, -1, "One Bit Mutation", (80, 10), 
                           wx.DefaultSize,mutation_list, wx.CB_DROPDOWN)
        self.mut_type.SetToolTip(wx.ToolTip("Type of Mutation:\n" \
                                            "One Bit Mutation: Flips one bit per gene with a certain probability\n"+\
                                            "Flips Several Bits Mutation: Flips each bit with a certain probability\n"+\
                                            "Bit Position Related : Non disruptive mutation, that has higer probability of mutating less significant genes"))

        self.Bind(wx.EVT_COMBOBOX, self.OnMutSelect, self.mut_type)
        
        prob_label=wx.StaticText(panel, -1, "Probability", pos=(10, 42))
        self.prob=wx.TextCtrl(panel, -1, "0.05", pos=(80, 40), size=(40, 20))
        self.prob.SetToolTip(wx.ToolTip("Value used for probabilty of mutation (0-1)"))
        self.prob.Enable(True)
        
        self.prob_top=wx.TextCtrl(panel, -1, "0.9", pos=(130, 40), size=(40, 20))
        self.prob_top.SetToolTip(wx.ToolTip("Top value of probability of mutation."))
        self.prob_top.Show(False)
        self.prob_top.Enable(False)
        
        self.prob_step=wx.TextCtrl(panel, -1, "0.05", pos=(180, 40), size=(40, 20))
        self.prob_step.SetToolTip(wx.ToolTip("Step value of probability of mutation."))
        self.prob_step.Show(False)
        self.prob_step.Enable(False)
        
        alpha_label=wx.StaticText(panel, -1, "Alpha", pos=(10, 62))
        self.alpha=wx.TextCtrl(panel, -1, "1", pos=(80, 60), size=(40, 20))
        self.alpha.SetToolTip(wx.ToolTip("Value used in weight of base probability formulae"))
        self.alpha.Enable(False)
        
        self.alpha_top=wx.TextCtrl(panel, -1, "5", pos=(130, 60), size=(40, 20))
        self.alpha_top.SetToolTip(wx.ToolTip("Top value for alpha"))
        self.alpha_top.Show(False)
        self.alpha_top.Enable(False)
        
        self.alpha_step=wx.TextCtrl(panel, -1, "1", pos=(180, 60), size=(40, 20))
        self.alpha_step.SetToolTip(wx.ToolTip("Step value for alpha"))
        self.alpha_step.Show(False)
        self.alpha_step.Enable(False)
       
        sigma_label=wx.StaticText(panel, -1, "Sigma", pos=(10, 82))
        self.sigma=wx.TextCtrl(panel, -1, "1", pos=(80, 80), size=(40, 20))
        self.sigma.SetToolTip(wx.ToolTip("Value used for mutation of parameters"))
        self.sigma.Enable(False)
        
        self.sigma_top=wx.TextCtrl(panel, -1, "2", pos=(130, 80), size=(40, 20))
        self.sigma_top.SetToolTip(wx.ToolTip("Top value for sigma."))
        self.sigma_top.Show(False)
        self.sigma_top.Enable(False)
        
        self.sigma_step=wx.TextCtrl(panel, -1, "0.5", pos=(180, 80), size=(40, 20))
        self.sigma_step.SetToolTip(wx.ToolTip("Step value for sigma."))
        self.sigma_step.Show(False)
        self.sigma_step.Enable(False)
              
        if(self.project_type!="Quickshot"):
            self.OnAddRuns()

    def OnMutSelect(self, event):
        evtObj=event.GetEventObject()                
        chosen=evtObj.GetValue()
        
        if (self.alg_type=="EE"):
            self.sigma.Enable(True)
            self.sigma_top.Enable(True)
            self.sigma_step.Enable(True)
        
        if (chosen=="One Bit Mutation"):
            self.alpha.Enable(False)
            self.alpha_top.Enable(False)
            self.alpha_step.Enable(False)

            self.prob.Enable(True)
            self.prob_top.Enable(True)
            self.prob_step.Enable(True)
            
        if (chosen=="Several Bits Mutation"):
            self.alpha.Enable(False)
            self.alpha_top.Enable(False)
            self.alpha_step.Enable(False)

            self.prob.Enable(True)
            self.prob_top.Enable(True)
            self.prob_step.Enable(True)            
            
        if (chosen=="Bit Position Related Mutation"):
            self.alpha.Enable(True)
            self.alpha_top.Enable(True)
            self.alpha_step.Enable(True)
            
            self.prob.Enable(False)
            self.prob_top.Enable(False)
            self.prob_step.Enable(False)            
            
    def OnAddRuns(self):
        
        self.alpha_top.Show(True)
        self.alpha_step.Show(True)
        
        self.sigma_top.Show(True)
        self.sigma_step.Show(True)

        self.prob_top.Show(True)
        self.prob_step.Show(True)
        
    def post_processing(self, event):
        
        if(not(self.validate())):
            dlg=wx.MessageDialog(self, "Values are not right!", "WRONG", wx.OK)
            dlg.ShowModal()
            dlg.Destroy()
            event.Veto()
        else:
            event.Allow()
        
        mut_content=contents.content()
        
        if self.mut_type.GetStringSelection()=="":
            mut_content.type="One Bit Mutation"
        else:
            mut_content.type=self.mut_type.GetStringSelection()
        
        mut_content.range_prob=[None]
        mut_content.range_sigma=[None]
        mut_content.range_alpha=[None]
        
        if(self.project_type=="Quickshot"):
            if (self.sigma.IsEnabled()==True):
                mut_content.range_sigma=[float(self.sigma.GetValue())]
	    
            if (self.prob.IsEnabled()==True):
                mut_content.range_prob=[float(self.prob.GetValue())]

            if (self.alpha.IsEnabled()==True):
                mut_content.range_alpha=[float(self.alpha.GetValue())]
        else:
            if (self.sigma.IsEnabled()==True):
                mut_content.range_sigma=arange(float(self.sigma.GetValue()),\
                                         float(self.sigma_top.GetValue()),\
                                         float(self.sigma_step.GetValue()))
                mut_content.range_prob=[None]
                mut_content.range_alpha=[None]
                
            if (self.prob.IsEnabled()==True):
                mut_content.range_prob=arange(float(self.prob.GetValue()),\
                                         float(self.prob_top.GetValue()),\
                                         float(self.prob_step.GetValue()))
                mut_content.range_sigma=[None]
                mut_content.range_alpha=[None]
                
            if (self.alpha.IsEnabled()==True):
                mut_content.alpha=self.alpha.GetValue()
                mut_content.range_alpha=arange(float(self.alpha.GetValue()),\
                                         float(self.alpha_top.GetValue()),\
                                         float(self.alpha_step.GetValue()))
                mut_content.range_prob=[None]
                mut_content.range_sigma=[None]   
            
        a=Singleton_Content()
        a.mut_c=mut_content
        
    def validate(self):
            
        try:
            if float(self.prob.GetValue()) < 0 or float(self.prob.GetValue()) > 1 :
                return False
        except ValueError: return False
        
        try:
            if float(self.sigma.GetValue()) < 0 :
                return False
        except ValueError: return False
        
        try:
            if float(self.alpha.GetValue()) < 0 :
                return False
        except ValueError: return False
        
        return True
    
class Population_Frame(wx.wizard.WizardPageSimple):
    
    def __init__(self, parent, title):
        wx.wizard.WizardPageSimple.__init__(self, parent)  
        self.population_panel = wx.Panel(self, -1)

        #self.Bind(wiz.EVT_WIZARD_CANCEL, self.OnWizCancel)
        self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.set_parameters)
        self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.post_processing)
        
        
    def set_parameters(self,alg_type="AG",project_type="Quickshot"):
        
        self.project_type = project_type
        self.alg_type = alg_type
        
        #Fill Up the main panel of the Frame
        self.fill_up_population_data(self.population_panel)
        
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.sizer)
        self.sizer.Add(self.population_panel , 0, wx.EXPAND)  
        

    def fill_up_population_data(self, panel):
        
        pop_number_label=wx.StaticText(panel, -1, "Number Of Individuals", pos=(10, 12))
        self.pop_number=wx.TextCtrl(panel, -1, "20", pos=(120, 10), size=(40, 20))
        self.pop_number.SetToolTip(wx.ToolTip("Number of individuals in population"))
        
        EE_variations_list=["All Variable Mutation Rate", 
                       "Independent Variable Mutation Rates"]
        
        if(self.alg_type=="EE"):
            variation_label=wx.StaticText(panel, -1, "Type Of Evolutionary Strategy", pos=(10, 42))
            self.mut_type = wx.ComboBox(panel, -1, "All Variable Mutation Rate", (160, 40), 
                           wx.DefaultSize,EE_variations_list, wx.CB_DROPDOWN)
                  
    def post_processing(self, event):
        
        if(not(self.validate())):
            dlg=wx.MessageDialog(self, "Values are not right!", "WRONG", wx.OK)
            dlg.ShowModal()
            dlg.Destroy()
            event.Veto()
        else:
            event.Allow()
        
        pop_content=contents.content()
        pop_content.pop_number=self.pop_number.GetValue()
        
        if(self.alg_type=="EE"):
            
            if self.mut_type.GetValue()=="":
                pop_content.mut_method="All Variable Mutation Rate"
            else:
                pop_content.mut_method=self.mut_type.GetValue()
            
        a=Singleton_Content
        a.pop_c=pop_content
              
    def validate(self):
       
        try: 
            if(int(self.pop_number.GetValue()) <= 1):
                return False
        except ValueError: return False
        
        return True          
    
class ParameterFrame(wx.wizard.WizardPageSimple):
    """ Class containing the whole Form for parameters of the AG, inserted
    by the user """
    
    def __init__(self, parent, title):        
        wx.wizard.WizardPageSimple.__init__(self, parent)  
        self.main_panel = wx.Panel(self, -1)
        
        #self.Bind(wiz.EVT_WIZARD_CANCEL, self.OnWizCancel)
        self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.set_parameters)
        self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.post_processing)
    
        
    def set_parameters(self, event):
        
        #Fill Up the main panel of the Frame
        self.fill_up_pane(self.main_panel)
        
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.sizer)
        self.sizer.Add(self.main_panel, 0, wx.EXPAND)
       
    def fill_up_pane(self, pane):
        """Creation of ALL the objects present in the form, except the Next 
        Button. Every addiction to the panel must be done in this function
        
        .Parameters:
        
            pane:        Panel to fill up
                                                
        .Return value:
        
            List Of Objects:    List containing the different objects in
                                        the screen
        
        """
        
        #List for inserting Algorythm
        list_type_alg=['GA', 'EE']
        self.type_alg_label=wx.StaticText(pane, -1, "Evolutionary Algorithm", pos=(10, 13))
        self.type_alg = wx.ComboBox(pane, -1, "GA", (130, 10), 
                           wx.DefaultSize,list_type_alg, wx.CB_DROPDOWN)
        self.type_alg.SetToolTip(wx.ToolTip("Type of Evolutionary Algorithm.\n" +\
                                                "GA - Genetic Algorithm\n" +\
                                                "EE - Evolutionary Algorithm"))
        
        #Number of Runs (Default is 1)
        self.nruns_label=wx.StaticText(pane, -1, "Number of Runs", pos=(10, 43))
        self.nruns=wx.TextCtrl(pane, -1, "1", pos=(130, 40))
        self.nruns.SetToolTip(wx.ToolTip("Number of times the project is executed"))
        
        #StopCondition
        self.stop_section_label=wx.StaticText(pane, -1, "Stop Condition:", pos=(10, 73))
        
        #Choose Stop Condition
        list_stop=['Target Quality', 'Number of Generations', 'Both']
        self.stop_label=wx.StaticText(pane, -1, "Stop Condition Type", pos=(10, 103))
        self.stop = wx.ComboBox(pane, -1, "Both", (130, 100), 
                           wx.DefaultSize,list_stop, wx.CB_DROPDOWN)
        self.Bind(wx.EVT_COMBOBOX, self.onConditionSelect, self.stop)
        self.stop.SetToolTip(wx.ToolTip("Stop Condition.\n" +\
                                                "Both - Stops, either when the target quality, or maxinum number of generations are achieved\n" +\
                                                "Target Quality - Stops when the target quality is achieved\n"+\
                                                "Number of Generations - Stops when the maxinum number of generations is achieved\n"))
        
        
        #Stop Condition Generations
        self.ngen_label=wx.StaticText(pane, -1, "Number of Generations", pos=(10, 133))
        self.ngen=wx.TextCtrl(pane, -1, "50", pos=(130, 130))
        self.ngen.SetToolTip(wx.ToolTip("Maxinum Number of Generations that the Algorithm runs.\n"))
        
        #Stop Condition Target Quality
        self.quality_label=wx.StaticText(pane, -1, "Target Quality", pos=(10, 163))
        self.quality=wx.TextCtrl(pane, -1, "0", pos=(130, 160))
        self.quality.SetToolTip(wx.ToolTip("Quality that, when achieved" +\
                                           "by the best individual, makes the algorithm stop.\n"))
            
    def validate(self):
       
        try: 
            if(int(self.nruns.GetValue()) <= 0):
                return False
        except ValueError: return False 
        
        s = self.stop.GetStringSelection()
        if(s==""):
            s="Both"
        
        if((s=="Both") | (s=="Number of Generations")):
            try: 
                i = int(self.ngen.GetValue())
                if(i < 0):
                    return False                
            except ValueError: return False
            
        if((s=="Both") | (s=="Target Quality")):
            try:
                f = float(self.quality.GetValue()=="")
            except ValueError: return False

        
        return True
              

    
    def post_processing(self, event):
        
        if(not(self.validate())):
            dlg=wx.MessageDialog(self, "Values are not right!", "WRONG", wx.OK)
            dlg.ShowModal()
            dlg.Destroy()
            event.Veto()
        else:
            event.Allow()
        
        c = contents.content()
        
        a=Singleton_Content()

        c.ngen=[None]
        c.quality=[None]
        c.type_project = "Quickshot" 
        
        if self.type_alg.GetStringSelection()=="":
            c.type_alg="GA"
        else:
            c.type_alg = self.type_alg.GetStringSelection()
        
        a.project_type=c.type_project
        a.alg_type=c.type_alg
        
        c.nruns = int(self.nruns.GetValue())
        if self.stop.GetStringSelection()=="":
            c.stop = "Both"
        else:
            c.stop = self.stop.GetStringSelection()
        if(c.stop == "Both"):
            c.ngen = int(self.ngen.GetValue())
            c.quality = float(self.quality.GetValue())
        elif(c.stop=="Target Quality"):
            c.quality = float(self.quality.GetValue())
        else:
            c.ngen = int(self.ngen.GetValue())

        a.ag_c=c
        a.nruns=int(self.nruns.GetValue())

    def onConditionSelect(self, event):
        evtObj = event.GetEventObject()
        chosen = evtObj.GetValue()
        
        if(chosen == "Both"):
            self.ngen.Show(True)
            self.ngen_label.Show(True)
            self.quality_label.Show(True)
            self.quality.Show(True) 
            
        if(chosen == "Target Quality"):
            self.ngen.Show(False)
            self.ngen_label.Show(False)
            self.quality_label.Show(True)
            self.quality.Show(True)       
        
        if(chosen == "Number of Generations"):
            self.ngen.Show(True)
            self.ngen_label.Show(True)
            self.quality_label.Show(False)
            self.quality.Show(False)   

class SelectionFrame(wx.wizard.WizardPageSimple):
    """ Class containing the whole Form for parameters of the AG, inserted
    by the user """
    
    def __init__(self, parent, title):
        wx.wizard.WizardPageSimple.__init__(self, parent)  
        self.main_panel = wx.Panel(self, -1)
        
        #self.Bind(wiz.EVT_WIZARD_CANCEL, self.OnWizCancel)
        self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGED, self.set_parameters)
        self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.post_processing)
    
        
    def set_parameters(self, event):
        
        a=Singleton_Content()
        
        self.project_type = a.project_type
        self.alg_type = a.alg_type
        
        #Fill Up the main panel of the Frame
        self.fill_up_pane(self.main_panel)
        
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(self.sizer)
        self.sizer.Add(self.main_panel, 0, wx.EXPAND)
        
        
    def fill_up_pane(self, pane):
        """Creation of ALL the objects present in the form, except the Next 
        Button. Every addiction to the panel must be done in this function
        
        .Parameters:
        
            pane:        Panel to fill up
                                                
        .Return value:
        
        """        
        #Number of Parents (Default is 2)
        self.nparents_label=wx.StaticText(pane, -1, "Number of Parents", pos=(10, 13))
        self.nparents=wx.TextCtrl(pane, -1, "2", pos=(130, 10),size=(50,20))
        self.nparents.SetToolTip(wx.ToolTip("Number of Parents for crossover"))
    
        #List for inserting ParentSelection type
        list_parent_sel=['Stochastic Sampling', 'Roulette', 'Tournament', 'Linear Ranking' , 'Exponential Ranking']
        self.parent_sel_label=wx.StaticText(pane, -1, "Parent Sel. Method", pos=(10, 43))
        self.parent_sel = wx.ComboBox(pane, -1, "Tournament", (130, 40), 
                           wx.DefaultSize,list_parent_sel, wx.CB_DROPDOWN)
        self.Bind(wx.EVT_COMBOBOX, self.onParentSelect, self.parent_sel)
        self.parent_sel.SetToolTip(wx.ToolTip("Parent Select Method:\n"+\
                                              "Stochastic Sampling - \n"+\
                                              "Roulette Wheel - \n" + \
                                              "Tournament - \n"+\
                                              "Linear Ranking - \n"+\
                                              "Exponential Ranking - \n"))
        
        #Number of Contestants (Default is 2)
        self.ncontestants_label=wx.StaticText(pane, -1, "Number of Contestants", pos=(10, 73))
        self.ncontestants=wx.TextCtrl(pane, -1, "2", pos=(130, 70),size=(50,20))
        self.ncontestants.SetToolTip(wx.ToolTip("Tournament's number of contestants.\n"))
        self.ncontestants_label.Show(True)
        self.ncontestants.Show(True)
        
        #Loosers Hype Percentage (Default is 0%)
        self.losers_hype_label=wx.StaticText(pane, -1, "Losers Hype (%)", pos=(10, 103))
        self.losers_hype=wx.TextCtrl(pane, -1, "0", pos=(130, 100),size=(50,20))
        self.losers_hype.SetToolTip(wx.ToolTip("Probability of tournament being won by the loser.\n"))
        self.losers_hype.Show(True)
        self.losers_hype_label.Show(True)
        
        
        self.higher_prob_label = wx.StaticText(pane, -1, "High Probability", pos=(10, 133))
        self.higher_prob=wx.TextCtrl(pane, -1, "0.1", pos=(130, 130),size=(50,20))
        self.higher_prob.SetToolTip(wx.ToolTip("Probability of Highest ranking individual being chosen.\n"))
        self.higher_prob.Show(False)
        self.higher_prob_label.Show(False)
        
        
        #TODO os Parametros de Ranking
        
        list_survivor_sel=['Chomp', 'Gerational', 'Best\Worst']
        self.survivor_sel_label=wx.StaticText(pane, -1, "Survivor Sel. Method", pos=(10, 163))
        self.survivor_sel = wx.ComboBox(pane, -1, "Gerational", (130, 163), 
                           wx.DefaultSize,list_survivor_sel, wx.CB_DROPDOWN)
        self.Bind(wx.EVT_COMBOBOX, self.onSurvivorSelect, self.survivor_sel)
        self.survivor_sel.SetToolTip(wx.ToolTip("Survivor Selection Method:\n" +\
                                                "Chomp - The Best individuals pass on to the next generation\n"+\
                                                "Gerational - Offspring always pass on to the next generation\n"+\
                                                "Best|Worst - A given probability of the best and worst \n" +
                                                "individuals passes on to the next generation.\n"))
        
        self.elitism_label = wx.StaticText(pane, -1, "Elitism", pos=(10, 190))      
        self.elitism= wx.TextCtrl(pane, -1, "1", pos=(130, 193),size=(50,20))
        self.elitism.SetToolTip(wx.ToolTip("Number of the best individuals "+\
                                           "that pass on to the next generation\n"))
        self.elitism_label.Show(True)
                   
        #Percentage Best/worst         
        self.percentage_Best_label = wx.StaticText(pane, -1, "Percentage Best", pos=(10, 193))
        self.percentage_Best_label.Show(False)

        self.percentage = []
        self.percentage.append(wx.TextCtrl(pane, -1, "0.75", pos=(130, 193), size=(40,30)))
        self.percentage[0].SetToolTip(wx.ToolTip("Percentage of Individuals of the " +\
                                                 "population that are considered the \"Best\"\n"))
        self.percentage[0].Show(False)
        self.percentage.append(wx.TextCtrl(pane, -1, "0.50", pos=(180, 193), size=(40,30)))
        self.percentage[1].SetToolTip(wx.ToolTip("Percentage of the \"Best\" Individuals that pass on to "+\
                                                 "the next generation.\"\n"))
        self.percentage[1].Show(False)     
    
    def onSurvivorSelect(self, event):
        evtObj = event.GetEventObject()
        chosen = evtObj.GetValue()

        if(chosen == "Best\Worst"):
            self.elitism_label.Show(False)
            self.elitism.Show(False)
            self.percentage_Best_label.Show(True)
            for i in range(0,2):
                self.percentage[i].Show(True)
            
        
        if(chosen != "Best\Worst"):
            self.elitism_label.Show(True)
            self.elitism.Show(True)
            self.percentage_Best_label.Show(False)
            for i in range(0,2):
                self.percentage[i].Show(False)
                                      

    def onParentSelect(self, event):
        evtObj = event.GetEventObject()
        chosen = evtObj.GetValue()
        
        if(chosen == "Tournament"):
            self.losers_hype.Show(True)
            self.losers_hype_label.Show(True)
            self.ncontestants_label.Show(True)
            self.ncontestants.Show(True)
            
        if(chosen != "Tournament"):
            self.losers_hype.Show(False)
            self.losers_hype_label.Show(False)
            self.ncontestants_label.Show(False)
            self.ncontestants.Show(False)
        
        if(chosen=="Linear Ranking"):
            self.higher_prob.Show(True)
            self.higher_prob_label.Show(True)
        else:
            self.higher_prob.Show(False)
            self.higher_prob_label.Show(False)
            
            
    def post_processing(self, event):
        
        if(not(self.validate())):
            dlg=wx.MessageDialog(self, "Values are not right!", "WRONG", wx.OK)
            dlg.ShowModal()
            dlg.Destroy()
            event.Veto()
        else:
            event.Allow()
        
        c = contents.content()
        
        c.high_prob = [None]
        c.ncontestants = [None]
        c.losers_hype = [None]
        c.survivor_sel = [None]
        c.elitism = [None]
        c.percentage = [None, None]
        
        c.nparents = [int(self.nparents.GetValue())]
        c.parent_sel = self.parent_sel.GetStringSelection()
        c.survivor_sel = self.survivor_sel.GetStringSelection()
            
        if c.parent_sel=="":
            c.parent_sel="Tournament"
       
        if c.survivor_sel=="":
            c.survivor="Gerational"
            
        if(c.parent_sel == "Tournament"):
            c.ncontestants = [int(self.ncontestants.GetValue())]
            c.losers_hype = [float(self.losers_hype.GetValue())]
        
        elif c.parent_sel == "Linear Ranking" :
            c.high_prob = [float(self.higher_prob.GetValue()) + 1.0 ]
            
        if(c.survivor_sel != "Best\Worst"):
            c.elitism = [int(self.elitism.GetValue())]
        else:
            c.percentage = []
            c.percentage.append(float(self.percentage[0].GetValue()))
            c.percentage.append(float(self.percentage[1].GetValue()))
        
        a=Singleton_Content()
        a.sel_c=c
 
    def validate(self):
	    
        sp = self.parent_sel.GetStringSelection()
        if(sp==""): sp = "Tournament"
            
        ss = self.survivor_sel.GetStringSelection()
        
        if(ss==""): ss = "Gerational"
        
        if(ss == "Best\Worst"):
            try:
                for i in range(0,2):
                    l = float(self.percentage[i].GetValue())
                    if((l >= 1.0) | (l <= 0.0)):
                        return False 
            except ValueError: return False
        else:
            try:
                i = int(self.elitism.GetValue())
                if(i < 0):
                    return False    
            except ValueError: return False 
        
        try: 
            if(int(self.nparents.GetValue()) < 2):
                return False
        except ValueError: return False
        
        if sp=="Tournament" :
            try:
                i = int(self.ncontestants.GetValue())
                l = float(self.losers_hype.GetValue())
                if(i < 2):
                    return False
                if((l > 1.0) | (l < 0.0) ):
                    return False    
            except ValueError: return False
            
        elif sp=="Ranking" :
            try:
                i = float(self.higher_prob.GetValue())
                if i > 1.0 or i < 0.0 : 
                    return False
            except ValueError: return

  
                
        return True
                
class FunctionFrame(wx.wizard.WizardPageSimple):
    """ Class containing the whole Form for function and problem input
    by the user """
    def __init__(self, parent, title):

    	self.daddy = parent
    	wx.wizard.WizardPageSimple.__init__(self, parent)  
    	main_panel = wx.Panel(self, -1)
    	self.sizer = wx.BoxSizer(wx.VERTICAL)
    	self.SetSizer(self.sizer)
    	self.sizer.Add(main_panel, 0, wx.EXPAND)
 
        self.fill_up_pane(main_panel)
        
        self.Bind(wx.wizard.EVT_WIZARD_PAGE_CHANGING, self.post_processing)

    def fill_up_pane(self, pane):
        """Creation of ALL the objects present in the form, except the Next 
        Button. Every addiction to the panel must be done in this function
        
        .Parameters:
        
            pane:        Panel to fill up
                                                
        .Return value:
        
            None
        
        """

        projname_label=wx.StaticText(pane, -1, "Project Name", pos=(10, 7))
        self.projname=wx.TextCtrl(pane, -1,"Projecto", pos=(90, 5))
        self.projname.SetToolTip(wx.ToolTip("Name of the project (and consequently its folder and project names)"))

        func_label=wx.StaticText(pane, -1, "Function", pos=(10, 37))
        self.func=wx.TextCtrl(pane, -1, "x+y", pos=(90, 35))
        self.func.SetToolTip(wx.ToolTip("Function to find its optimum (Python notation)"))

        vars_label=wx.StaticText(pane, -1, "Variables Used", pos=(10, 62))
        self.vars=wx.TextCtrl(pane, -1, "x,y", pos=(90, 60))
        self.vars.SetToolTip(wx.ToolTip("List with the variables used by the function (example: \"x,y,z\")"))
        
        list_type=['Maximization', 'Minimization']
        type_label=wx.StaticText(pane, -1, "Type", pos=(200, 37))
        self.type = wx.ComboBox(pane, -1, "Maximization", (230, 35), 
                           wx.DefaultSize,list_type, wx.CB_DROPDOWN)
        self.type.SetToolTip(wx.ToolTip("Optimum type - Maximum or minimum"))
        
        prec_label=wx.StaticText(pane, -1, "Precision", pos=(200, 62))
        self.prec=wx.TextCtrl(pane, -1, "0.01,0.01", pos=(250, 60), size=(70, 20))
        self.prec.SetToolTip(wx.ToolTip("Precision list for each variable (example, for (x,y,z): \"10**-6,10**-6,10**-6\""))
        
        restr_label=wx.StaticText(pane, -1, "Restrictions", pos=(10, 102))
        self.restr_button=wx.Button(pane, label="Add", pos=(80, 100), size=(30,20))
        self.restr_button_rem=wx.Button(pane, label="Remove", pos=(115, 100), size=(50,20))
        self.Bind(wx.EVT_BUTTON, self.AddRestriction, self.restr_button)
        self.Bind(wx.EVT_BUTTON, self.RemoveRestriction, self.restr_button_rem)
        self.restr = wx.ListBox(pane, -1,  (10, 130), (100, 80), [], wx.LB_SINGLE)
        self.restr.SetToolTip(wx.ToolTip("Dominium Restrictions,\n"+\
                                        "should be in the form (x<function(x,y)), example: \"x>y**2\""))
          
        lims_label=wx.StaticText(pane, -1, "Limits", pos=(180, 102))
        self.lims_button=wx.Button(pane, label="Add", pos=(250, 100), size=(30,20))
        self.lims_button_rem=wx.Button(pane, label="Remove", pos=(285, 100), size=(50,20))
        self.Bind(wx.EVT_BUTTON, self.AddLimit, self.lims_button)
        self.Bind(wx.EVT_BUTTON, self.RemoveLimit, self.lims_button_rem)
        self.lims = wx.ListBox(pane, -1,  (180, 130), (100, 80), [], wx.LB_SINGLE)
        self.lims.SetToolTip(wx.ToolTip("Boundary Limits for each variable,\n"+\
                                        "should be in the form (xmin<x<xmax), example:(0<x<10)"))
        
        wei_label=wx.StaticText(pane, -1, "Penalty Weight", pos=(10, 242))
        self.weights=wx.TextCtrl(pane, -1, "5", pos=(90, 240), size=(30,20))
        self.weights.SetToolTip(wx.ToolTip("Penalty for each broken restriction"))
        
        self.lims.Append("0<x<100")
        self.lims.Append("0<y<100")
           
       
    def AddRestriction(self, event):
        dlg = wx.TextEntryDialog(
                self, 'Enter the desired variable restriction')
        dlg.ShowModal()
        if dlg.GetValue() != "":
            self.restr.Append(dlg.GetValue())
        
    def RemoveRestriction(self,event):
        try:
            self.restr.Delete(self.restr.GetSelection())
        except: 
            pass
   
    def RemoveLimit(self,event):
        try:
            self.lims.Delete(self.lims.GetSelection())
        except: 
            pass
   
    def AddLimit(self, event):
        dlg = wx.TextEntryDialog(
                self, 'Enter the desired variable limit')
        dlg.ShowModal()
        s = dlg.GetValue()
        if s != "" :
            self.lims.Append(s)
 
    def post_processing(self, event):
        
        if(not(self.validate())):
            dlg=wx.MessageDialog(self, "Values are not right!", "WRONG", wx.OK)
            dlg.ShowModal()
            dlg.Destroy()
            event.Veto()
        else:
            event.Allow()
        
     
                
        func_content=contents.content()
        func_content.function=self.func.GetValue()
        func_content.variables=self.vars.GetValue()
        func_content.precision=self.prec.GetValue()
        
        if self.type.GetStringSelection()=="":
            func_content.type="Maximization"
        else:
            func_content.type=self.type.GetStringSelection()  
        
        rest_list=[]
        for i in range(0, self.restr.GetCount()):
            rest_list.append(self.restr.GetString(i))
        
        func_content.restrictions=rest_list
        
        lim_list=[]
        for i in range(0, self.lims.GetCount()):
            lim_list.append(self.lims.GetString(i))
        
        func_content.limits=lim_list
        func_content.weight=self.weights.GetValue()
        
        a=Singleton_Content()
        a.function_c=func_content
        
        a.project_name=self.projname.GetValue();
        
    def validate(self):
        
        def split_function( string_to_split, separator_list):
            listy=[string_to_split]
            for i in separator_list:
                new_list=[]
                for j in listy:
                    new_list.extend(j.split(i))
                listy=new_list
                
            newl=[]
            for val in listy:
                if val.isdigit():
                    continue
                elif val=="":
                    continue
                else:
                    newl.extend(val)
            return newl
        
        def is_correct_form( stringy):
            
            listy=stringy.split("<")
            if (len(listy)!=3):
                return False
            if(listy[0]>listy[2]):
                return False
            return True
        
        
        
        vars=self.vars.GetValue().split(",")
        precs=self.prec.GetValue().split(",")
        
        if(self.projname.GetValue()==""):
            print "No Project Name"
        
        if os.path.isdir(self.projname.GetValue()):
            print 'project already exists'
            return False
        
        f_vars=split_function(self.func.GetValue(), ["+","-","*","/", "(", ")"])
        
        exceptions=["sin","cos"]
        nl=[]
        lista = f_vars
        for thingy in lista:
            passy=0
            for excepty in exceptions:
                if(thingy==excepty):
                    passy=1
                if(passy==0):
                    nl.append(thingy)
            if passy == 1:
                nl.append(thingy)
        f_vars=nl
        
        
        if(f_vars==vars):
            print "Variables OK"
        else:
            print "Variables KO"
        
        if( len(precs)==len(vars)):
            print "Precision OK"
        else:
            print "Precision KO"
            return False
        
        lim_list=[]
        for i in range(0, self.lims.GetCount()):
            lim_list.append(self.lims.GetString(i))
            
        limmy=[]
        for i in lim_list:
            if(not(is_correct_form(i))):
               print "Not Correct Form"
               return False
            else:   
               limmy.append(i.split("<")[1])
       
        for i in vars:
            if(limmy.count(i)!=1):
                print "Not right limits"
                return False
                
        print "ALL DONE"
        return True
              

def beginWizard():
    
    canceled = True
    #app = wx.PySimpleApp()
    image = wx.Image('ernesto.jpg',wx.BITMAP_TYPE_JPEG)
    temp= image.ConvertToBitmap()
    
    wizard = wx.wizard.Wizard(None, -1, "Wizard",temp)
    wizard.SetPageSize(wx.Size(380,100))
    #wizard.Bind(wx.wizard.EVT_WIZARD_CANCEL, On_Cancel)
    page1 = FunctionFrame(wizard, "Page 1",)
    page2 = ParameterFrame(wizard, "Page 2")
    page3 = Population_Frame(wizard, "Page 3")
    page4 = SelectionFrame(wizard, "Page 4")
    page5 = Crossover_Frame(wizard, "Page 5")
    page6 = Mutation_Frame(wizard, "Page 5")
    
    wx.wizard.WizardPageSimple_Chain(page1, page2)
    wx.wizard.WizardPageSimple_Chain(page2, page3)
    wx.wizard.WizardPageSimple_Chain(page3, page4)
    wx.wizard.WizardPageSimple_Chain(page4, page5)
    wx.wizard.WizardPageSimple_Chain(page5, page6)
    wizard.FitToPage(page1)
    
    page1.SetPrev(page1)
    page2.SetPrev(page2)
    page3.SetPrev(page3)
    page4.SetPrev(page4)
    page5.SetPrev(page5)
    page6.SetPrev(page6)
   
    if wizard.RunWizard(page1):
        proj=create_project()
        canceled = False

    
    wizard.Destroy()
    wizard.DestroyChildren()
    
    if not canceled:
        return proj
    else:
        return None

def create_project():
       
    a=Singleton_Content()
    
    ##Project argument 1: Class Function (DONE)
    
    fc=a.function_c
    
    precision_dictionary={}
    listy_var=fc.variables.split(",")
    listy_pre=fc.precision.split(",")
    
    for i in listy_var:
        precision_dictionary[i]=listy_pre[listy_var.index(i)]
    
    limit_dictionary={}
    limit_dictionary=limit_dictionary.fromkeys(listy_var)

    for i in fc.limits:
        listy=i.split("<")
        for val in limit_dictionary:
            if(i.find(listy[1])!=-1):
                limit_dictionary[listy[1]]=[float(listy[0]), float(listy[2])]
                
    for i in precision_dictionary:
        for j in limit_dictionary:
            if (i==j):
                listy=limit_dictionary[j]
                listy.append(float(eval(precision_dictionary[i])))
                limit_dictionary[j]=listy
    
    precision=fc.precision
    
    prbclass=function.Problem(fc.function, fc.restrictions,\
                               limit_dictionary, fc.type, fc.weight)
    
    
    #args: prbclass
    
    ##Project Argument 2: Project Name (DONE)
    
    #args=a.project_name
    
    ##Project Argument 3: Project Parameters (DONE)
    
    ptype=a.project_type
    atype=a.alg_type
    nruns=int(a.nruns)
    
    #args=ptype, atype, nruns
    
    ##Project Argument 4: Class Stop Condition (DONE)
    
    ac=a.ag_c
    stop_c=ac.stop
    
    list=[]
    
    if(stop_c == "Both"):
        str_stop="generation_or_quality_stop"
        list.append(ac.quality)
        list.append(ac.ngen)
    elif(stop_c=="Number of Generations"):
        str_stop="generation_end_stop"
        list.append(None)
        list.append(ac.ngen)
    else:
        str_stop="quality_achieved_stop"
        list.append(ac.quality)
        list.append(None)
    
    #stpclass=stop_condition.StopCondition(stop_c, list) 
    
    #args: strstop, list
    
    ##Project Argument 5: Population (List) (DONE)
    
    pc=a.pop_c
    p_stats=[int(pc.pop_number)]

    ##Project Argument 6: Mutation [callable, [range(Prob), range(alpha), range(sigma)]
    
    mc=a.mut_c
    if(mc.type=="Bit Position Related Mutation"):
        m="flip_bits_position_related_mutation"
        
    if(mc.type=="Several Bits Mutation"):
        m="flip_several_bits_mutation"
        
    if(mc.type=="One Bit Mutation"):
        m="flip_one_bit_mutation"
    
    m_ranges=[m, mc.range_prob, mc.range_alpha, mc.range_sigma]
    
    #args: [m, m_ranges]
    
    
    ##Project Argument 5: Crossover [callable, range(prob), range(numPoints), range(weight)]
    
    rc=a.cross_c
    
    if(rc.type=="One Point Crossover"):
        r="one_point_crossover"
        
    if(rc.type=="N Point Crossover"):
        r="n_points_crossover"
        
    if(rc.type=="Uniform Crossover"):
        r="uniform_crossover"

        
    r_ranges=[r,rc.prob, rc.npoints, rc.weight]
    
    #args: r, r_ranges

    ##Project Argument 7: ParentSelection [callable, range(arity),range(num_contestants), range(losers_hype)]
    
    sel=a.sel_c
    
    if (sel.parent_sel=="Stochastic Sampling"):
        sp="stochastic_universal_sampling_select"
    
    if (sel.parent_sel=="Roulette"):
        sp="roulette_select"
    
    if (sel.parent_sel=="Tournament"):
        sp="tournament_select"
    
    if (sel.parent_sel=="Linear Ranking"):
        sp="order_select_linear"
        
    if (sel.parent_sel=="Exponential Ranking"):
        sp="order_select_exponential"
    
    sp_ranges=[sp, sel.nparents, sel.ncontestants, sel.losers_hype, sel.high_prob]
    
    #args: sp, sp_ranges
    
    ##Project Argument 8: SurvivorSelection [callable, range(elitism), range(pop_div), range(best_pass)]
    
    list_survivor_sel=['Chomp', 'Gerational', 'Best\Worst']
    
    ss="gerational_select"
    
    if (sel.survivor_sel=="Chomp"):
        ss="chomp_select"
    
    if (sel.survivor_sel=="Gerational"):
        ss="gerational_select"
    
    if (sel.survivor_sel=="Best\Worst"):
        ss="best_worst_select"

    ss_ranges=[ss,sel.elitism, [sel.percentage[0]],[sel.percentage[1]]]
    
    #args: ss, ss_ranges
    
    ######TESTING###########
    
    ##Longshot:
    ##Function = Class Function
    ##Stop Condition = Class StopCondition 
    ##Population = []
    ##Mutation = [ (callable), range(Prob), range(alpha), range(sigma)]
    ##Crossover = [string (callable), range(prob), range(numPoints), range(weight)]
    ##ParentSelection = [string (callable), range(arity),range(num_contestants), range(losers_hype)]
    ##SurvivorSelection = [string (callable), range(elitism), range(pop_div), range(best_pass)]
    ##
    ##On Quickshot range lists are replaced with unitary lists with a single value
    
    proj=project.Project()
    
    proj.set_project(a.project_name, [ptype, atype, nruns], prbclass, \
                    [str_stop, list],p_stats, m_ranges, \
                    r_ranges, sp_ranges, ss_ranges)

    return a.project_name
